/******************************************************
 Copyright (C) 2014 Yucheng Yao. All rights reserved.
 *******************************************************
 this file defines 2 structs: float3 and double3.And
 typedef float3 as v3 when without USE_DOUBLE defined. So
 if you have defined USE_DOUBLE befor include this file,
 v3 is double3's alias.
 *******************************************************
 */
#ifndef CRYSTAL_DOUBLE3_H
#define CRYSTAL_DOUBLE3_H
#include <cmath>
#include "float3.h"
namespace crystal {

	struct double3 {
		double x, y, z;

		double3(double x, double y, double z) :
				x(x), y(y), z(z) {
		}
		double3(const double3 &u) :
				x(u.x), y(u.y), z(u.z) {
		}
		double3(const float3 &u) :
				x(u.x), y(u.y), z(u.z) {
		}
		double3() :
				x(0), y(0), z(0) {
		}
		operator float3()const{
			return float3(x,y,z);
		}
		double module() const;
		//double3 normalization() const; 
		void normalize();

	};

	/***********inline implementation for double3************/

	inline double double3::module() const {
		return sqrt(x * x + y * y + z * z);
	}
	inline void double3::normalize() {
		double m = module();
		x /= m;
		y /= m;
		z /= m;
	}

	inline double3 operator-(const double3 &u) {
		return double3(-u.x, -u.y, -u.z);
	}
	inline double3 operator+(const double3 &u, const double3 &v) {
		return double3(u.x + v.x, u.y + v.y, u.z + v.z);
	}
	inline double3 operator-(const double3 &u, const double3 &v) {
		return double3(-v + u);
	}
	inline double operator*(const double3 &u, const double3 &v) {
		return u.x * v.x + u.y * v.y + u.z * v.z;
	}
	inline double3 operator*(const double &a, const double3 &u) {
		return double3(a * u.x, a * u.y, a * u.z);
	}
	inline double3 operator*(const double3 &u, const double &a) {
		return a * u;
	}
	inline double3 operator/(const double3 &u, const double &a) {
		return 1.0f / a * u;
	}
	inline double3 operator^(const double3 &u, const double3 &v) {
		double x = u.y * v.z - u.z * v.y;
		double y = u.z * v.x - u.x * v.z;
		double z = u.x * v.y - u.y * v.x;
		return double3(x, y, z);
	}
}
#endif
